<!-- TrendChart.vue -->
<template>
    <v-chart v-if="ready" ref="myChartRef" class="chart" :option="option" />
</template>

<script setup lang="ts" generic="T extends string | number">
import { ref, computed, watchEffect, nextTick, onMounted, type Ref } from "vue";
import { graphic } from "echarts/core";
import type { ECharts } from "echarts/core";
/* -------------------- 类型定义 -------------------- */
interface SeriesConfig {
    name: string; // 图例名称
    color: string; // 主色  rgba(252,144,16,.7)
    data: number[]; // 数据
    showMaxMark?: boolean; // 是否显示最大值 markPoint
}

interface Props {
    /* 核心数据 */
    /* 关键：用 Ref<> 包装，让外部直接传 ref()  */
    xData: Ref<T[]>;
    series: Ref<SeriesConfig[]>;
    /* 外观 */
    smooth?: boolean; // 是否平滑曲线
    grid?: Record<string, any>; // 覆盖默认 grid
}

/* -------------------- Props / Emits -------------------- */
const props = withDefaults(defineProps<Props>(), {
    smooth: true,
    grid: () => ({
        show: true,
        left: "10px",
        right: "30px",
        bottom: "10px",
        top: "32px",
        containLabel: true,
        borderColor: "#1F63A3",
    }),
});

/* -------------------- 计算 option -------------------- */
const ready = ref(false);
const myChartRef = ref<ECharts | null>(null);
const option = computed(() => ({
    xAxis: {
        type: "category",
        data: props.xData.value,
        boundaryGap: false,
        splitLine: {
            show: true,
            lineStyle: { color: "rgba(31,99,163,.2)" },
        },
        axisLine: {
            lineStyle: { color: "rgba(31,99,163,.1)" },
        },
        axisLabel: { color: "#7EB7FD", fontWeight: "500" },
    },
    yAxis: {
        type: "value",
        splitLine: {
            show: true,
            lineStyle: { color: "rgba(31,99,163,.2)" },
        },
        axisLine: {
            lineStyle: { color: "rgba(31,99,163,.1)" },
        },
        axisLabel: { color: "#7EB7FD", fontWeight: "500" },
    },

    tooltip: {
        trigger: "axis",
        backgroundColor: "rgba(0,0,0,.6)",
        borderColor: "rgba(147,235,248,.8)",
        textStyle: { color: "#FFF" },
    },
    grid: props.grid,
    series: props.series.value.map(s => ({
        name: s.name,
        type: "line",
        data: s.data,
        smooth: props.smooth,
        symbol: "none",
        color: s.color,
        areaStyle: {
            color: new graphic.LinearGradient(
                0,
                0,
                0,
                1,
                [
                    { offset: 0, color: s.color },
                    { offset: 1, color: s.color.replace(/[\d.]+\)$/, "0)") },
                ],
                false
            ),
        },
        markPoint: s.showMaxMark
            ? {
                  data: [
                      {
                          type: "max",
                          valueDim: "y",
                          symbol: "rect",
                          symbolSize: [60, 26],
                          symbolOffset: [0, -20],
                          itemStyle: { color: "rgba(0,0,0,0)" },
                          label: {
                              color: s.color.replace(/[\d.]+\)$/, "1)"),
                              backgroundColor: s.color.replace(/[\d.]+\)$/, "0.1)"),
                              borderColor: s.color.replace(/[\d.]+\)$/, "0.5)"),
                              borderWidth: 0.5,
                              borderRadius: 6,
                              padding: [7, 14],
                              formatter: `${s.name}：{c}`,
                          },
                      },
                      {
                          type: "max",
                          valueDim: "y",
                          symbol: "circle",
                          symbolSize: 6,
                          itemStyle: {
                              color: s.color.replace(/[\d.]+\)$/, "1)"),
                              shadowColor: s.color.replace(/[\d.]+\)$/, "1)"),
                              shadowBlur: 8,
                          },
                          label: { formatter: "" },
                      },
                  ],
              }
            : undefined,
    })),
}));

/* -------------------- 生命周期 -------------------- */
// 当数据为空时避免渲染，等外部拿到数据后再画
watchEffect(async () => {
    const bool = !!(props.xData?.value?.length && props.series?.value?.length);
    if (bool) {
        await nextTick();
        setTimeout(() => {
            myChartRef.value && myChartRef.value?.resize?.();
        }, 200);
    }
    ready.value = bool;
});

onMounted(() => {});
</script>

<style lang="scss" scoped>
.chart {
    width: 100%;
    height: 100%;
    .vue-echarts-inner {
        height: 100% !important;
    }
}
</style>
